package com.ruoyi.project.monitor.controller

import com.ruoyi.common.constant.CacheConstants
import com.ruoyi.framework.web.domain.AjaxResult
import com.ruoyi.project.monitor.domain.SysCache
import org.apache.commons.lang3.StringUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.connection.RedisConnection
import org.springframework.data.redis.core.RedisCallback
import org.springframework.data.redis.core.RedisTemplate
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import java.util.*
import java.util.function.Consumer
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

/**
 * 缓存监控
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/cache")
open class CacheController {
    @Autowired
    private val redisTemplate: RedisTemplate<String, String>? = null

    companion object {
        private val caches: MutableList<SysCache> = ArrayList()
    }

    init {
        caches.add(SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"))
        caches.add(SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"))
        caches.add(SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"))
        caches.add(SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"))
        caches.add(SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"))
        caches.add(SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"))
        caches.add(SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"))
    }

    @get:Throws(Exception::class)
    @get:GetMapping
    @get:PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    val info: AjaxResult
        get() {
            val info =
                    redisTemplate!!.execute { connection: RedisConnection -> connection.info() } as Properties
            val commandStats =
                    redisTemplate.execute(RedisCallback<Any> { connection: RedisConnection -> connection.info("commandstats") }) as Properties
            val dbSize =
                    redisTemplate.execute(RedisCallback<Any> { connection: RedisConnection -> connection.dbSize() })
            val result: MutableMap<String, Any> = HashMap(3)
            result["info"] = info
            result["dbSize"] = dbSize!!
            val pieList: MutableList<Map<String, String>> = ArrayList()
            commandStats.stringPropertyNames().forEach(Consumer { key: String? ->
                val data: MutableMap<String, String> = HashMap(2)
                val property = commandStats.getProperty(key)
                data["name"] = StringUtils.removeStart(key, "cmdstat_")
                data["value"] = StringUtils.substringBetween(property, "calls=", ",usec")
                pieList.add(data)
            })
            result["commandStats"] = pieList
            return AjaxResult.success(result)
        }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getNames")
    fun cache(): AjaxResult {
        return AjaxResult.success(caches)
    }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getKeys/{cacheName}")
    fun getCacheKeys(@PathVariable cacheName: String): AjaxResult {
        val cacheKeys = redisTemplate!!.keys("$cacheName*")
        return AjaxResult.success(cacheKeys)
    }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getValue/{cacheName}/{cacheKey}")
    fun getCacheValue(@PathVariable cacheName: String, @PathVariable cacheKey: String): AjaxResult {
        val cacheValue = redisTemplate!!.opsForValue()[cacheKey]
        val sysCache = cacheValue?.let { SysCache(cacheName, cacheKey, it) }
        return AjaxResult.success(sysCache)
    }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheName/{cacheName}")
    fun clearCacheName(@PathVariable cacheName: String): AjaxResult {
        val cacheKeys: Collection<String> = redisTemplate!!.keys("$cacheName*")
        redisTemplate.delete(cacheKeys)
        return AjaxResult.success()
    }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheKey/{cacheKey}")
    fun clearCacheKey(@PathVariable cacheKey: String): AjaxResult {
        redisTemplate!!.delete(cacheKey)
        return AjaxResult.success()
    }

    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheAll")
    fun clearCacheAll(): AjaxResult {
        val cacheKeys: Collection<String> = redisTemplate!!.keys("*")
        redisTemplate.delete(cacheKeys)
        return AjaxResult.success()
    }
}
